var nextGlobalId  = 1,
    nextIdByScope = {},
    P_ID = '__def_id__';

def.nextId = function(scope) {
    if(scope) {
        var nextId = def.getOwn(nextIdByScope, scope) || 1;
        nextIdByScope[scope] = nextId + 1;
        return nextId;
    }

    return nextGlobalId++;
};

/**
 * Obtains the id of an object or function.
 * @param {Object} inst The value whose id to obtain.
 * @return {string} the hash key.
 */
def.id = function(inst) {
    var id = def.getOwn(inst, P_ID);
    if(!id) def.setConst(inst, P_ID, (id = def.nextId()));
    return id;
};

/**
 * Obtains the hash key for a given value.
 *
 * Sample hash-keys generated by this function.
 * <dl>
 *     <dt><tt>null</tt></dt><dd><tt>"o:null"</tt></dd>
 *     <dt><tt>undefined</tt></dt><dd><tt>"u:undefined"</tt></dd>
 *     <dt><tt>1</tt></dt><dd><tt>"n:1"</tt></dd>
 *     <dt><tt>true</tt></dt><dd><tt>"b:true"</tt></dd>
 *     <dt><tt>"abc"</tt></dt><dd><tt>"s:abc"</tt></dd>
 *     <dt><tt>""</tt></dt><dd><tt>"s:"</tt></dd>
 *     <dt><tt>{a: 1}</tt></dt><dd><tt>"o:1"</tt></dd>
 *     <dt><tt>[1]</tt></dt><dd><tt>"o:2"</tt></dd>
 *     <dt><tt>new Date()</tt></dt><dd><tt>"o:3"</tt></dd>
 * </dl>
 *
 * @param {*} value The value whose hash key to obtain.
 * @return {string} the hash key.
 */
def.hashKey = function(value) {
    var t = (typeof value).charAt(0);
    switch(t) {
        case 'n': // number
        case 'b': // boolean
        case 's': // string
            return t + ":" + value;
        // case f-unction
        // case o-bject
        // case u-ndefined
        // other... u-nknown, ...
    }

    // value can be null or undefined

    // Arrays, Dates, etc, are not handled specially.
    return t + ":" + (value ? value : def.id(value));
};